package com.bflow.commons.service;

import com.bflow.commons.bean.PageBean;
import com.bflow.commons.bean.PageResult;
import com.bflow.commons.bean.QueryParam;
import com.bflow.commons.dao.IBaseDao;
import com.bflow.commons.exception.BizException;
import com.bflow.commons.po.BasePo;
import com.bflow.util.AssertUtil;
import com.bflow.util.BeanMapper;
import com.bflow.util.Reflections;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * @name：基础Service
 * @author：xuhaowen
 * @date：2018-12-13
 */
public abstract class BaseService<P extends BasePo, B extends Serializable> implements IBaseService<P, B> {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 根据id查询
     *
     * @param id
     * @return
     */
    public B findById(Serializable id) {
        if(id == null)
            return null;
        P data = getDao().findById(id);
        if (data != null) {
            return BeanMapper.map(data, getBoClazz());
        }
        return null;
    }

    /**
     * 根据ids查询
     *
     * @param ids
     * @return
     */
    public List<B> findByIds(Serializable... ids) {
        List<P> data = getDao().findByIds(ids);
        if (data != null && data.size() > 0) {
            return BeanMapper.mapList(data, getBoClazz());
        }
        return null;
    }

    /**
     * 根据ids查询
     * @param ids
     * @return
     */
    public List<B> findByIds(List ids) {
        if(ids == null || ids.isEmpty())
            return null;
        return findByIds(StringUtils.join(ids, ",").split(","));
    }

    /**
     * 根据id删除实体
     *
     * @return 刪除记录数
     */
    public int deleteById(Serializable id) {
        if(id == null || id.toString().length() == 0)
            throw new BizException("删除失败，参数缺失");
        return getDao().deleteById(id);
    }

    /**
     * 根据id删除实体
     *
     * @param ids
     * @return
     */
    public int deleteByIds(Serializable... ids) {
        if(ids == null || ids.length == 0)
            throw new BizException("删除失败，参数缺失");
        return getDao().deleteByIds(ids);
    }

    /**
     * 根据paramBean条件进行删除
     *
     * @param paramBean
     * @return
     */
    public int deleteBy(B paramBean) {
        P po = null;
        if (paramBean != null) {
            po = BeanMapper.map(paramBean, getPoClazz());
        }
        return getDao().deleteBy(po);
    }

    /**
     * 根据paramBean条件进行删除
     *
     * @param queryParam
     * @return
     */
    public int deleteBy(QueryParam queryParam) {
        return getDao().deleteBy(queryParam);
    }

    /**
     * 新增
     *
     * @param entity 实体
     * @return 保存数据的记录数
     */
    public int insert(B entity) {
        P po = null;
        if (entity != null) {
            po = BeanMapper.map(entity, getPoClazz());
        }
        return getDao().insert(po);
    }

    /**
     * 更新
     *
     * @param entity 实体
     * @return 更新数据的记录数
     */
    public int update(B entity) {
        P po = null;
        if (entity != null) {
            po = BeanMapper.map(entity, getPoClazz());
        }
        return getDao().update(po);
    }

    /**
     * 批量新增
     *
     * @param entities 实体集合
     */
    public void batchInsert(List<B> entities) {
        if (entities.isEmpty()) {
            return;
        }
        List<P> poList = BeanMapper.mapList(entities, getPoClazz());
        getDao().batchInsert(poList);
    }

    /**
     * 批量更新
     *
     * @param entities 实体集合
     */
    public void batchUpdate(List<B> entities) {
        if (entities.isEmpty()) {
            return;
        }
        List<P> poList = BeanMapper.mapList(entities, getPoClazz());
        getDao().batchUpdate(poList);
    }

    /**
     * 根据param条件查询数据
     *
     * @param param
     * @return
     */
    public List<B> findByParam(QueryParam param) {
        List<P> data = getDao().findBy(param);
        if (data != null && data.size() > 0) {
            return BeanMapper.mapList(data, getBoClazz());
        }
        return null;
    }

    /**
     * 根据条件查询唯一数据记录
     *
     * @param param
     * @return
     */
    public B findUniqueByParam(QueryParam param) {
        P data = getDao().findUniqueBy(param);
        if (data != null) {
            return BeanMapper.map(data, getBoClazz());
        }
        return null;
    }

    public B getOneBy(B bo){
        P po = getDao().findUniqueBy(new QueryParam(bo));
        if (po != null) {
            return BeanMapper.map(po, getBoClazz());
        }
        return null;
    }

    public List<B> getListBy(B bo){
        List<P> list = getDao().findBy(new QueryParam(bo));
        if (CollectionUtils.isNotEmpty(list)) {
            return BeanMapper.mapList(list, getBoClazz());
        }
        return null;
    }

    public List<B> findAll() {
        return findByParam(new QueryParam());
    }

    public Object getMaxId() {
        return getDao().getMaxId();
    }

    /**
     * 根据BaseQuery条件查询分页数据
     *
     * @param queryParam 查询条件
     * @return
     */
    public PageResult<B> findPage(QueryParam queryParam) {
        PageResult<B> pageResult = new PageResult<B>();
        List<B> dataList = null;
        if (queryParam != null && queryParam.getPageBean() != null) {
            PageBean pageBean = queryParam.getPageBean();
            queryParam.addExtendParam("_pageCountQuery_", "true");
            long totalCount = getDao().findPageCount(queryParam);
            queryParam.removeExtendParam("_pageCountQuery_");
            if (totalCount <= 0) {
                dataList = new ArrayList<B>();
            } else {
                List<P> data = getDao().findPage(queryParam, new RowBounds(pageBean.getStart(), pageBean.getPageSize()));
                if (data != null && data.size() > 0) {
                    dataList = BeanMapper.mapList(data, getBoClazz());
                }
            }
            pageResult.setTotalCount(totalCount);
        } else {
            List<P> data = getDao().findPage(queryParam);
            if (data != null && data.size() > 0) {
                dataList = BeanMapper.mapList(data, getBoClazz());
            }
        }
        if (dataList != null) {
            pageResult.setResult(dataList);
        }
        return pageResult;
    }

    @SuppressWarnings("unchecked")
    public Class<P> getPoClazz() {
        return Reflections.getSuperClassGenricType(getClass(), 0);
    }

    @SuppressWarnings("unchecked")
    public Class<B> getBoClazz() {
        return Reflections.getSuperClassGenricType(getClass(), 1);
    }

    protected abstract IBaseDao<P> getDao();
}

